﻿package com.game.engine
{
	import base.BaseAura;
	import base.BaseBullet;
	import base.BaseHero;
	import base.BaseLevelListener;
	import base.BaseMonster;
	import base.BaseObject;
	import base.BaseSummon;
	import base.BaseTerrain;
	
	import com.dusk.util.ArrayUtil;
	
	import com.dusk.util.ResUtil;
	import com.game.view.component.MonsterAppearPoint;
	import com.game.view.component.StopPoint;
	import com.game.view.component.TransDoor;
	
	import config.Config;
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.system.System;
	
	public class PhysicsWorld
	{
		
		public function PhysicsWorld()
		{
			super();
			gc = Config.getIns();
		}
		
		
		
		private var _heroArray:Array = [];
		private var _auraArray:Array = [];
		private var _dropArray:Array = [];
		private var _summonArray:Array = [];
		private var _monsterArray:Array = [];
		private var _terrainArray:Array = [];
		private var _stopPointArray:Array = [];
		private var _transferDoorArray:Array = [];
		private var _monsterAppearPointArray:Array = [];
		
		private var _sourceReady:Boolean = false;
		private var _levelListener:BaseLevelListener;
		private var gc:Config;
		
		public function addSubObj(obj:DisplayObject):void
		{
			if (!(obj is MovieClip)) return;
			var mc:MovieClip = obj as MovieClip;
			var terrain:BaseTerrain = null;
			if (mc.getChildByName("isWall"))
			{
				terrain = new BaseTerrain();
				terrain.buildFromSprite(mc);
				_terrainArray.push(terrain);
				CONFIG::DEBUG
				{
					mc.visible = true;
				}
				CONFIG::RELEASE
				{
					mc.visible = false;
				}
			}
			if (mc.getChildByName("isThroughWall"))
			{
				terrain = new BaseTerrain();
				terrain.buildFromSprite(mc);
				_terrainArray.push(terrain);
				CONFIG::DEBUG
				{
					mc.visible = true;
				}
				CONFIG::RELEASE
				{
					mc.visible = false;
				}
			}
			if (mc.getChildByName("isThroughUpButDownWall"))
			{
				terrain = new BaseTerrain();
				terrain.buildFromSprite(mc);
				_terrainArray.push(terrain);
				CONFIG::DEBUG
				{
					mc.visible = true;
				}
				CONFIG::RELEASE
				{
					mc.visible = false;
				}
			}
			if (mc.getChildByName("isThroughDownButUpWall"))
			{
				terrain = new BaseTerrain();
				terrain.buildFromSprite(mc);
				_terrainArray.push(terrain);
				CONFIG::DEBUG
				{
					mc.visible = true;
				}
				CONFIG::RELEASE
				{
					mc.visible = false;
				}
			}
		}
		
		public function pWorldInit():void
		{
			_levelListener = ResUtil.getNewObj("export.level.StageListener" + MainGame.getIns().levelData.curStage + MainGame.getIns().levelData.curLevel) as BaseLevelListener;
			_levelListener.init();
		}
		
		public function pWorldStart():void
		{
			_sourceReady = true;
			if (gc.team.getHeroArray().length == 1)
			{
				gc.maxMonsterPerScreen = 6;
			}
			else
			{
				gc.maxMonsterPerScreen = 8;
			}
		}
		
		public function getHeroArray():Array
		{
			return _heroArray;
		}
		
		public function getMonsterArray():Array
		{
			return _monsterArray;
		}
		
		public function getTerrainArray():Array
		{
			return _terrainArray;
		}
		
		public function getTransferDoorArray():Array
		{
			return _transferDoorArray;
		}
		
		public function getStopPointArray():Array
		{
			return _stopPointArray;
		}
		
		public function getMonsterAppearArray():Array
		{
			return _monsterAppearPointArray;
		}
		
		public function getAuraArray():Array
		{
			return _auraArray;
		}
		
		public function getDropArray():Array
		{
			return _dropArray;
		}
		
		public function getSummonArray():Array
		{
			return _summonArray;
		}
		
		public function getBaseLevelListener():BaseLevelListener
		{
			return _levelListener;
		}
		
		public function render(ratio:Number = 1):void
		{
			if (!_sourceReady)
			{
				return;
			}
			for each(var mon:BaseMonster in _monsterArray)
			{
				if (!mon.isReadyToDestroy)
				{
					for each(var monBullet:BaseBullet in mon.magicBulletArray)
					{
						if (!monBullet.isReadyToDestroy)
						{
							monBullet.render(ratio);
						}
					}
					mon.render(ratio);
				}
			}
			for each(var hero:BaseHero in _heroArray)
			{
				if (!hero.isReadyToDestroy)
				{
					for each(var heroBullet:BaseBullet in hero.magicBulletArray)
					{
						if (!heroBullet.isReadyToDestroy)
						{
							heroBullet.render(ratio);
						}
					}
					hero.render(ratio);
				}
			}
			for each(var summon:BaseSummon in _summonArray)
			{
				if (!summon.isReadyToDestroy)
				{
					for each(var summonBullet:BaseBullet in summon.magicBulletArray)
					{
						if (!summonBullet.isReadyToDestroy)
						{
							summonBullet.render(ratio);
						}
					}
					summon.render();
				}
			}
			for each(var wall:BaseTerrain in _terrainArray)
			{
				if (!wall.isReadyToDestroy)
				{
					wall.render(ratio);
				}
			}
			for each(var door:TransDoor in _transferDoorArray)
			{
				if(!door.isReadyToDestroy)
				{
					door.render(ratio);
				}
			}
			for each(var monAppear:MonsterAppearPoint in _monsterAppearPointArray)
			{
				if(!monAppear.isReadyToDestroy)
				{
					monAppear.render(ratio);
				}
			}
			for each(var stopPoint:StopPoint in _stopPointArray)
			{
				if(!stopPoint.isReadyToDestroy)
				{
					stopPoint.render(ratio);
				}
			}
			for each(var aura:BaseAura in _auraArray)
			{
				if (!aura.isReadyToDestroy)
				{
					aura.render(ratio);
				}
			}
			for each (var fallObj:BaseObject in _dropArray)
			{
				if(!fallObj.isReadyToDestroy)
				{
					fallObj.render(ratio);
				}
			}
		}
		
		public function renderAnimate():void
		{
			if (!_sourceReady)
			{
				return;
			}
			var bulTrash:Array = [];
			var objTrash:Array = [];
			
			/*=================================================================*/
			for each(var mon:BaseMonster in _monsterArray)
			{
				if(mon.isReadyToDestroy)
				{
					objTrash.push(mon);
					continue;
				}
				for each (var monBul:BaseBullet in mon.magicBulletArray)
				{
					if(monBul.isReadyToDestroy)
					{
						bulTrash.push(monBul);
						continue;
					}
					monBul.renderAnimate();
				}
				remove(bulTrash, mon.magicBulletArray);
				mon.renderAnimate();
			}
			remove(objTrash, _monsterArray);
			
			/*=================================================================*/
			for each(var hero:BaseHero in _heroArray)
			{
				if (hero.isReadyToDestroy)
				{
					objTrash.push(hero);
					continue;
				}
				for each (var heroBul:BaseBullet in hero.magicBulletArray)
				{
					if (heroBul.isReadyToDestroy)
					{
						bulTrash.push(heroBul);
						continue;
					}
					heroBul.renderAnimate();
				}
				remove(bulTrash, hero.magicBulletArray);
				hero.renderAnimate();
			}
			remove(objTrash, _heroArray);
			
			/*=================================================================*/
			for each(var summon:BaseSummon in _summonArray)
			{
				if (summon.isReadyToDestroy)
				{
					objTrash.push(summon);
					continue;
				}
				for each (var likeMonBul:BaseBullet in summon.magicBulletArray)
				{
					if (likeMonBul.isReadyToDestroy)
					{
						bulTrash.push(likeMonBul);
						continue;
					}
					likeMonBul.renderAnimate();
				}
				remove(bulTrash, summon.magicBulletArray);
				summon.renderAnimate();
			}
			remove(objTrash, _summonArray);
			
			/*=================================================================*/
			for each(var wall:BaseTerrain in _terrainArray)
			{
				if(wall.isReadyToDestroy)
				{
					objTrash.push(wall);
					continue;
				}
				wall.renderAnimate();
			}
			remove(objTrash, _summonArray);
			
			/*=================================================================*/
			for each(var door:TransDoor in _transferDoorArray)
			{
				if(door.isReadyToDestroy)
				{
					objTrash.push(door);
					continue;
				}
				door.renderAnimate();
			}
			remove(objTrash, _transferDoorArray);
			
			/*=================================================================*/
			for each(var monAppear:MonsterAppearPoint in _monsterAppearPointArray)
			{
				if(monAppear.isReadyToDestroy)
				{
					objTrash.push(monAppear);
					continue;
				}
				monAppear.renderAnimate();
			}
			remove(objTrash, _monsterAppearPointArray);
			
			/*=================================================================*/
			for each(var stopPoint:StopPoint in _stopPointArray)
			{
				if(stopPoint.isReadyToDestroy)
				{
					objTrash.push(stopPoint);
					continue;
				}
				stopPoint.renderAnimate();
			}
			remove(objTrash, _stopPointArray);
			
			/*=================================================================*/
			for each(var aura:BaseAura in _auraArray)
			{
				if(aura.isReadyToDestroy)
				{
					objTrash.push(aura);
					continue;
				}
				aura.renderAnimate();
			}
			remove(objTrash, _auraArray);
			
			/*=================================================================*/
			for each (var fallObj:BaseObject in _dropArray)
			{
				if(fallObj.isReadyToDestroy)
				{
					objTrash.push(fallObj);
					continue;
				}
				fallObj.renderAnimate();
			}
			remove(objTrash, _dropArray);
			
			/*=================================================================*/
			if (_dropArray.length > gc.maxFallObj)
			{
				_dropArray[0].destroy();
			}
			if (_levelListener)
			{
				_levelListener.step();
			}
		}
		
		public function destroy():void
		{
			var destroyFunc:Function = function (item:*,a:*,b:*):void
			{
				item.destroy();
			}
			_monsterArray.forEach(destroyFunc);
			_monsterArray = [];
			_heroArray.forEach(destroyFunc);
			_heroArray = [];
			_summonArray.forEach(destroyFunc);
			_summonArray = [];
			_terrainArray.forEach(destroyFunc);
			_terrainArray = [];
			_transferDoorArray.forEach(destroyFunc);
			_transferDoorArray = [];
			_monsterAppearPointArray.forEach(destroyFunc);
			_monsterAppearPointArray = [];
			_stopPointArray.forEach(destroyFunc);
			_stopPointArray = [];
			_auraArray.forEach(destroyFunc);
			_auraArray = [];
			_dropArray.forEach(destroyFunc);
			_dropArray = [];
			_summonArray.forEach(destroyFunc);
			_summonArray = [];
			if (_levelListener)
			{
				_levelListener.destroy();
				_levelListener = null;
			}
			_sourceReady = false;
			System.gc();
		}
		
		private function remove(arr1:Array, arr2:Array):void
		{
			ArrayUtil.removeElementFromAnother(arr1, arr2);
		}
	}
}
